// 函数柯里化
// 函数将多元参数的调用拆解成更小参数甚至一元参数的调用

const _ = require('lodash');

function sum(a, b, c) {
  return a + b + c;
}

const currySum = _.curry(sum);

console.log(currySum(1, 2, 3));
console.log(currySum(1)(2)(3));
console.log(currySum(1)(2, 3));

function curry(fn) {
  return function curriedFn(...args) {
    if (args.length >= fn.length) {
      return fn(...args);
    } else {
      return function () {
        return curriedFn(...args.concat(Array.from(arguments)));
      };
    }
  };
}

const currySum1 = curry(sum);
console.log(currySum1(1, 2, 3));
console.log(currySum1(1)(2)(3));
console.log(currySum1(1)(2, 3));

// 柯里化函数的时候也可以接受参数
function curry2(fn, ...args) {
  if (args.length >= fn.length) {
    return fn(...args);
  }
  return function (...args1) {
    return curry2(fn, ...args, ...args1);
  };
}

const currySum2 = curry2(sum, 1);
console.log(currySum2(2, 3));
console.log(currySum2(2)(3));

// 柯里化相关案例
''.match(/\s+/g);
''.match(/\d+/g);

function match(reg, str) {
  return str.match(reg);
}

const curryMatch = curry2(match);

const haveSpace = curryMatch(/\s+/g);

console.log(haveSpace('hello world'));
console.log(haveSpace('helloworld'));

const haveNumber = curryMatch(/\d+/g);

console.log(haveNumber('123abc'));
console.log(haveNumber('abc'));

const curryFilter = curry2(function (func, arr) {
  return arr.filter(func);
});

console.log(curryFilter(haveSpace, ['json stan', 'json_stan']));

const filterSpace = curryFilter(haveSpace);

console.log(filterSpace(['json_stan', 'json stan']));
